Unsafe
java不能直接访问操作系统底层,而是通过本地方法来访问。Unsafe类提供了硬件级别的原子操作
1. Unsafe调用
Unsafe类是一个单例,调用的方法为getUnsafe。
getUnsafe()内部会检查该CallerClass是不是由系统类加载器BootstrapClassLoader加载。
由系统类加载器加载的类调用getClassLoader()会返回null,所以要检查类是否为bootstrap加载器加载只需要检查该方法是不是返回null。
1 | public final class Unsafe { |
调用Unsafe方法:
- 通过
JVM参数-Xbootclasspath指定要使用的类为启动类; - 在Unsafe类中有一个成员变量
theUnsafe,因此我们可以通过反射将private单例实例的accessible设置为true,然后通过Field的get方法获取
1 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); |
可以通过allocateInstance方法在未调用构造方法的情况下生成对象
1 | public native Object allocateInstance(Class<?> var1) throws InstantiationException; |
2. 内存操作
1 | public native long allocateMemory(long l); //分配内存 |
3. 对象某字段内存值操作
1 | public native long staticFieldOffset(Field var1); //对给定Field的定位,返回Field的内存地址偏移量 |
*_BASE_OFFSET常量: 通过arrayBaseOffset本地方法实现,返回数组中第一个元素的偏移地址
*_INDEX_SCALE常量: 通过arrayIndexScale 本地方法实现,获取数组的转换因子,也就是数组中元素的增量地址
通过二者结合,可定位数组中每个元素在内存中的位置
4. 线程挂起和恢复
1 | public native void unpark(Object var1); //终止一个挂起的线程,使其恢复正常 |
封装在LockSupport 类中
5. CAS操作
1 | /** |
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。
